package com.neu.flashmall.ms.service.impl;

import com.neu.common.constant.RedisRegion;
import com.neu.flashmall.ms.entity.SysMenu;
import com.neu.flashmall.ms.entity.SysRole;
import com.neu.flashmall.ms.entity.SysRoleMenu;
import com.neu.flashmall.ms.entity.SysUser;
import com.neu.flashmall.ms.mapper.SysMenuMapper;
import com.neu.flashmall.ms.mapper.SysRoleMapper;
import com.neu.flashmall.ms.mapper.SysRoleMenuMapper;
import com.neu.flashmall.ms.service.SysRoleMenuService;
import com.neu.flashmall.ms.service.SysUserService;
import com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil;
import com.neu.flashmall.ms.vo.SysUserVo;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class SysRoleMenuServiceImpl implements SysRoleMenuService {

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    @Cacheable(value = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
            key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).generateRoleToMenuIdListKey(#role)")
    public List<Long> getMenuIdByRole(Integer role) {
        return this.sysRoleMenuMapper.selectAllMenuIdByRoleId(role);
    }


    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
                    key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).ROLE_TO_MENU_ID_SET_MAP"),
            @CacheEvict(cacheNames = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
                    key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).generateRoleToMenuIdListKey(#id)")
    })
    public String updateRoleMenu(List<SysRoleMenu> sysRoleMenuList,Long id) {
        if(id == null) return "id异常";
        if(id.equals(1)){
            return "超级管理员权限不允许修改";
        }
        if(sysRoleMenuList.isEmpty()){
            this.sysRoleMenuMapper.deleteByRoleId(id);
            return "更新权限成功";
        }
        this.sysRoleMenuMapper.deleteByRoleId(id);
        int result = this.sysRoleMenuMapper.updateRoleMenu(sysRoleMenuList);
        if(result > 0){
            return "更新权限成功";
        }
        return "数据库未知错误";
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
                    key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).ROLE_TO_MENU_ID_SET_MAP"),
            @CacheEvict(cacheNames = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
                    key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).generateRoleToMenuIdListKey(#roleId)")
    })
    public int deleteRoleMenuByRole(Long roleId) {
        return this.sysRoleMenuMapper.deleteByRoleId(roleId);
    }

    @Override
    public String getAllAuthority() {
        this.sysRoleMenuMapper.deleteByRoleId(1L);
        List<SysMenu> allSysMenu = this.sysMenuMapper.selectAll();
        int result = this.sysRoleMenuMapper.superAdminGetAllAuthority(allSysMenu);
        if(result == allSysMenu.size()){
            return "获取所有权限成功";
        }
        return "数据库异常";
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
                    key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).ROLE_TO_MENU_ID_SET_MAP")
    })
    public String deleteAllOtherRoleAuthority(String username,String password) {
        SysUserVo sysUserVo = this.sysUserService.login(username,password);
        if(sysUserVo == null){
            return "身份验证失败";
        }
        SysUser sysUser = sysUserVo.getUser();
        if(sysUser == null){
            return "身份验证失败";
        }
        if(!sysUser.getRole().equals(1)){
            return "您不是超级管理员，您无权做此操作";
        }
        this.sysRoleMenuMapper.deleteAllOtherRoleAuthority();
        //更新数据库之后，用失效模式来解决缓存一致性问题
        this.toRemoveAllRoleToMenuIdListKeyFromRedis();
        return "删除成功";
    }

    /**
     * 创建出一个map，key是Role的id，value是该role所有拥有的SysMenu的id的集合
     * @return
     */
    @Override
    @Cacheable(value = {RedisRegion.FLASH_MALL_MANAGE_SYSTEM_REGION},
            key = "T(com.neu.flashmall.ms.utils.ManageSystemRedisKeyUtil).ROLE_TO_MENU_ID_SET_MAP")
    public HashMap<String, Set<Long>> getRoleToMenuIdSetMap() {
        List<SysRole> roleList = this.sysRoleMapper.selectAll();
        HashMap<String,Set<Long>> result = new HashMap<>();
        for(SysRole role : roleList){
            Integer id = Integer.valueOf(String.valueOf(role.getId()));
            List<Long> menuIdList = this.sysRoleMenuService.getMenuIdByRole(id);
            HashSet<Long> menuIdSet = new HashSet<>(menuIdList);
            result.put(role.getId().toString(),menuIdSet);
        }
        return result;
    }

    private long toRemoveAllRoleToMenuIdListKeyFromRedis(){
        Set<String> keys = redisTemplate.keys(ManageSystemRedisKeyUtil.
                generateKey(ManageSystemRedisKeyUtil.generateRoleToMenuIdListKey("*")));
        return redisTemplate.delete(keys);
    }


}
